package com.xiaoyan.texteditor.UI;

import com.xiaoyan.texteditor.service.*;
import sun.awt.WindowClosingListener;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyStore;

/**
 * ClassName: EditorUI
 * Package: com.xiaoyan.texteditor.UI
 * Description:
 * 文本编辑器的UI界面
 * 功能：
 *      1.显示正常信息
 *      2.点击功能正常
 * @Author Xiaoyan_Lu
 * @Create 2023/12/1 17:25
 * @Version 1.0
 */
public class EditorUI extends JFrame{
    private static final int WIDTH = 700;
    private static final int HEIGHT = 450;
    private static final int WINDOWS_X = 500;
    private static final int WINDOWS_Y = 500;
    //记事本文本框
    private JTextArea jTextArea = new JTextArea();
    //文件项
    JMenuItem jMenuItemNew = null;
    JMenuItem jMenuItemOpen = null;
    JMenuItem jMenuItemSave = null;
    JMenuItem jMenuItemSaveAs = null;
    JMenuItem jMenuItemExit = null;
    JMenuItem jMenuItemShear = null;
    JMenuItem jMenuItemCopy = null;
    JMenuItem jMenuItemPaste = null;
    JMenuItem jMenuItemAutomaticLineWrapping = null;
    JMenuItem jMenuItemFont = null;
    JMenuItem jMenuItemHelp = null;
    JMenuItem jMenuItemAbout = null;

    //文件选择对象
    JFileChooser jFileChooser = null;

    //保存文件服务
    private SaveFileService saveFileService = new SaveFileServiceImpl();
    //打开文件服务
    private OpenFileService openFileService = new OpenFileServiceImpl();
    //编辑服务
    private EditorService editorService = new EditorServiceImpl();
    //当前文本是否被修改
    private Boolean isChanged = false;//反映文本是否保存
    //当前文本的路径
    private String filePath = "";
    public EditorUI() throws HeadlessException {
        this.setSize(WIDTH,HEIGHT);
        //设置窗口显示位置
        this.setLocation(WINDOWS_X,WINDOWS_Y);
        //设置布局模式
        this.setLayout(new BorderLayout());
        //设置窗口的标题
        this.setTitle("鲁小研的记事本");
        //设置窗口的logo
        this.setIconImage(new ImageIcon("TextEditor/resources/icons/logo.png").getImage());
        //不允许用户改变窗口大小
//        this.setResizable(false);
        //设置菜单栏
        this.setMyMenuBar();
        //设置文本区域
        this.setTextArea();
        //设置底部信息区域
//        this.setBottomInfo();
        //设置窗口最小的大小比例
        this.setMinimumSize(new Dimension(WIDTH,HEIGHT));
        //当关闭窗口的时候，程序完全退出
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //显示窗口
        this.setVisible(true);
        //关闭后动作
        this.closingOperation();
    }

    private void closingOperation() {
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                jMenuItemExit.doClick();
                //当取消的时候，则不关闭对话框
                setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
            }
        });
    }

    /* *
     * @Description: 设置编辑器底部的信息区域
     * @param []
     * @return void
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/2 15:29
     */
//    private void setBottomInfo() {
//        JLabel jLabel = new JLabel("第三行第六列，共有字符数：233个，标点符号：122个");
//        jLabel.setPreferredSize(new Dimension(WIDTH,25));
//        this.getContentPane().add(jLabel,BorderLayout.SOUTH);
//    }

    /* *
     * @Description: 设置文本区域
     * @param []
     * @return void
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/2 15:25
     */
    private void setTextArea() {
        //设置边界距离
        this.jTextArea.setMargin(new Insets(5,5,5,5));
        //设置字体
        this.jTextArea.setFont(new Font("微软雅黑", Font.PLAIN,16));
        //给textarea添加监听器
        jTextArea.getDocument().addDocumentListener(new JTextAreaListener());
        //给textarea添加鼠标监听器
//        jTextArea.addMouseListener(new JTextAreaMouseListener());
        //添加滚动条
        JScrollPane jScrollPane = new JScrollPane(this.jTextArea);

        this.getContentPane().add(jScrollPane,BorderLayout.CENTER);
    }

    private void setMyMenuBar() {
        //创建菜单栏对象
        JMenuBar jMenuBar = new JMenuBar();

        //创建菜单对象
        JMenu jMenuFile = new JMenu("文件");
        JMenu jMenuEdit = new JMenu("编辑");
        jMenuEdit.addMenuListener(new EditListener());
        JMenu jMenuFormat = new JMenu("格式");
        JMenu jMenuHelp = new JMenu("帮助");
        jMenuBar.add(jMenuFile);
        jMenuBar.add(jMenuEdit);
        jMenuBar.add(jMenuFormat);
        jMenuBar.add(jMenuHelp);

        //创建菜单项,并设置快捷键
        jMenuItemNew = new JMenuItem("新建");
        jMenuItemNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
        jMenuItemOpen = new JMenuItem("打开");
        jMenuItemOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,InputEvent.CTRL_MASK));
        jMenuItemSave = new JMenuItem("保存");
        jMenuItemSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK));
        jMenuItemSaveAs = new JMenuItem("另存为");
        jMenuItemSaveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_MASK|InputEvent.SHIFT_MASK));
        jMenuItemExit = new JMenuItem("退出");
        jMenuItemShear = new JMenuItem("剪切");
        jMenuItemShear.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,InputEvent.CTRL_MASK));
        jMenuItemShear.setEnabled(false);
        jMenuItemCopy = new JMenuItem("复制");
        jMenuItemCopy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,InputEvent.CTRL_MASK));
        jMenuItemCopy.setEnabled(false);
        jMenuItemPaste = new JMenuItem("粘贴");
        jMenuItemPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_MASK));
        jMenuItemAutomaticLineWrapping = new JCheckBoxMenuItem("自动换行");
        jMenuItemAutomaticLineWrapping.setSelected(false);//默认取消
        jMenuItemFont = new JMenuItem("字体");
        jMenuItemHelp = new JMenuItem("查看帮助");
        jMenuItemAbout = new JMenuItem("关于记事本");

        //将菜单项添加到对应的菜单中
        jMenuFile.add(jMenuItemNew);
        jMenuFile.add(jMenuItemOpen);
        jMenuFile.add(jMenuItemSave);
        jMenuFile.add(jMenuItemSaveAs);
        jMenuFile.add(jMenuItemExit);

        jMenuEdit.add(jMenuItemShear);
        jMenuEdit.add(jMenuItemCopy);
        jMenuEdit.add(jMenuItemPaste);

        jMenuFormat.add(jMenuItemAutomaticLineWrapping);
        jMenuFormat.add(jMenuItemFont);

        jMenuHelp.add(jMenuItemHelp);
        jMenuHelp.add(jMenuItemAbout);

        //将菜单栏对象添加到窗体的菜单栏中
        this.setJMenuBar(jMenuBar);

        //给菜单项注册事件
        jMenuItemNew.addActionListener(new MenuItemNewHandler());
        jMenuItemOpen.addActionListener(new MenuItemOpenHandler());
        jMenuItemSave.addActionListener(new MenuItemSaveHandler());
        jMenuItemSaveAs.addActionListener(new MenuItemSaveAsHandler());
        jMenuItemExit.addActionListener(new MenuItemExitHandler());
        jMenuItemShear.addActionListener(new MenuItemShearHandler());
        jMenuItemCopy.addActionListener(new MenuItemCopyHandler());
        jMenuItemPaste.addActionListener(new MenuItemPasteHandler());
        jMenuItemAutomaticLineWrapping.addActionListener(new MenuItemAutomaticLineWrappingHandler());
        jMenuItemFont.addActionListener(new MenuItemFontHandler());
        jMenuItemHelp.addActionListener(new MenuItemHelpHandler());
        jMenuItemAbout.addActionListener(new MenuItemAboutHandler());
    }

    /* *
     * @Description: 文本区域监听器，监听内容是否被修改
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/3 18:06
     */
    private class JTextAreaListener implements DocumentListener{

        @Override
        public void insertUpdate(DocumentEvent e) {
            isChanged = true;
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            isChanged = true;
        }

        /* *
         * @Description: 检测文本是否被修改
         * @param [javax.swing.event.DocumentEvent]
         * @return void
         * @version v1.0
         * @author xiaoyan_lu
         * @date 2023/12/3 18:10
         */
        @Override
        public void changedUpdate(DocumentEvent e) {
            isChanged = true;
        }
    }

    private class MenuItemNewHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
//            System.out.println("新建一个文件");
            if(isChanged){//已修改的
                //先保存
                int confirmDialog = JOptionPane.showConfirmDialog(EditorUI.this, "是否保存修改?");
                if(confirmDialog == JOptionPane.YES_OPTION){
                    jMenuItemSave.doClick();
                }
            }
            //未修改的或者不保存的，直接新建
            //1.新建文件
            //1.1清空文本框
            jTextArea.setText("");
            //1.2更新isChanged
            isChanged = false;
            //1.3更新filepath
            filePath = "";
        }
    }

    /* *
     * @Description: 打开文件 监听器
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/3 16:49
     */
    private class MenuItemOpenHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            //打开文件
            //1.先判断当前信息是否保存，先保存，然后打开另一个文件
            if(isChanged){//文件改变了，未保存
                //1.1先保存
                int select = JOptionPane.showConfirmDialog(EditorUI.this, "是否保存修改?");
                if(select == JOptionPane.YES_OPTION){//保存
                    jMenuItemSave.doClick();
                }
            }
            //已经保存了，或者不需要保存
            //2.打开文件
            openFileWindows();
            isChanged = false;
        }
    }

    private void openFileWindows() {
        jFileChooser = new JFileChooser();
        //设置文件过滤器,过滤出txt文件
        FileNameExtensionFilter fileNameExtensionFilter = new FileNameExtensionFilter("*.txt","txt");
        jFileChooser.setFileFilter(fileNameExtensionFilter);

        //打开指定文件，返回状态码
        //showOpenDialog()参数主要作用dialog打开时的位置，是取决于父级组件还是什么；
        //如果参数为null,则说明dialog的位置取决于屏幕
        int returnVal = jFileChooser.showOpenDialog(EditorUI.this);
        if(returnVal == JFileChooser.APPROVE_OPTION){//打开没问题
            File selectedFile = jFileChooser.getSelectedFile();
            //2.直接打开新的文件
            StringBuilder openFileContent = openFileService.open(selectedFile, jTextArea);
            jTextArea.setText(openFileContent.toString());
            //3.保存打开文件的路径
            filePath = selectedFile.getAbsolutePath();
        }else{//打开失败
            System.out.println("打开失败");
        }
    }

    /* *
     * @Description: 保存监听器
     * @param
     * @return 
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/2 22:30
     */
    private class MenuItemSaveHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            //1.如果是旧文档，则直接保存文件
            if(!filePath.equals("")){
                saveFileService.save(filePath,jTextArea);
            }else{
                //2.如果是新建立的文档
                //设置保存的弹窗，并进行保存操作
                setSaveWindow();
            }
            //3.保存文件后，更新状态
            isChanged = false;
//            System.out.println(isChanged);
        }
    }

    /* *
     * @Description: 设置保存弹窗
     * @param []
     * @return void
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/3 19:54
     */
    private void setSaveWindow() {
        jFileChooser = new JFileChooser();
        //设置默认文件名
        jFileChooser.setSelectedFile(new File("*.txt"));
        int returnVal = jFileChooser.showSaveDialog(EditorUI.this);
        if(returnVal == JFileChooser.APPROVE_OPTION){//打开没问题
            File selectedFile = jFileChooser.getSelectedFile();
            //保存文件操作
            saveFileService.save(selectedFile.getAbsolutePath(),jTextArea);
            //更新路径
            filePath = selectedFile.getAbsolutePath();
            System.out.println(filePath);
        }else{//打开失败
            System.out.println("保存失败");
        }
    }

    /* *
     * @Description: 另存为 监听器
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/3 21:31
     */
    private class MenuItemSaveAsHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            setSaveWindow();
        }
    }

    /* *
     * @Description: 退出监听器
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/3 21:37
     */
    private class MenuItemExitHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            //1.未修改的文件直接退出
            if(isChanged){//已修改
                //2.已修改的文件需要保存然后退出
                //2.1旧的文件则直接保存原路径
                //2.3新的文件则需要建立保存路径
                if(filePath.equals("")){//新的文件
                    int confirmDialog = JOptionPane.showConfirmDialog(EditorUI.this, "是否要保存 无标题 文件?");
                    if(confirmDialog == JOptionPane.YES_OPTION){
                        setSaveWindow();
                        System.exit(0);
                    }
                    if(confirmDialog == JOptionPane.NO_OPTION){
                        System.exit(0);
                    }
                }else {//旧的文件
                    int confirmDialog = JOptionPane.showConfirmDialog(EditorUI.this, "是否保存到 " + filePath + ".txt 路径中");
                    if(confirmDialog == JOptionPane.YES_OPTION){
                        saveFileService.save(filePath,jTextArea);
                        System.exit(0);
                    }
                    if(confirmDialog == JOptionPane.NO_OPTION){
                        System.exit(0);
                    }
                }
            }else{
                System.exit(0);
            }
        }
    }

    /* *
     * @Description: 剪切
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/4 16:09
     */
    private class MenuItemShearHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
           editorService.shear(jTextArea.getSelectedText());
           //将选中的文本删除
           jTextArea.replaceRange("",jTextArea.getSelectionStart(),jTextArea.getSelectionEnd());
        }
    }

    /* *
     * @Description: 复制
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/4 16:09
     */
    private class MenuItemCopyHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String selectedText = jTextArea.getSelectedText();
            editorService.copy(selectedText);
        }
    }

    private class MenuItemPasteHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String paste = editorService.paste();
            jTextArea.replaceRange(paste,jTextArea.getSelectionStart(),jTextArea.getSelectionEnd());
        }
    }

    private class MenuItemAutomaticLineWrappingHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            //选中了就自动换行
            if(jMenuItemAutomaticLineWrapping.isSelected()){
                jTextArea.setLineWrap(true);
            }else {
                jTextArea.setLineWrap(false);
            }
            System.out.println(jMenuItemAutomaticLineWrapping.isSelected());
        }
    }

    /* *
     * @Description: 字体设置器
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/5 21:54
     */
    private class MenuItemFontHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            FontDialog fontDialog = new FontDialog(EditorUI.this,jTextArea);
            fontDialog.setVisible(true);
            System.out.println(jMenuItemFont.getText());
        }
    }

    /* *
     * @Description: 点击帮助自动跳转到百度页面
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/7 18:39
     */
    private class MenuItemHelpHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if(Desktop.isDesktopSupported()){
                try {
                    Desktop.getDesktop().browse(new URI("https://www.baidu.com/s?wd=有问题不会百度吗?"));
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                } catch (URISyntaxException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
    }

    /* *
     * @Description: 关于记事本信息
     * @param
     * @return
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/7 18:42
     */
    private class MenuItemAboutHandler implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            AboutDialog aboutDialog = new AboutDialog(EditorUI.this);
            aboutDialog.setVisible(true);
        }
    }

    private class EditListener implements MenuListener {
        /* *
         * @Description: 菜单被点击的时候，判断是否显示复制/粘贴菜单项
         * @param [javax.swing.event.MenuEvent]
         * @return void
         * @version v1.0
         * @author xiaoyan_lu
         * @date 2023/12/4 17:08
         */
        @Override
        public void menuSelected(MenuEvent e) {
            //先判断是否选中文本，选中才可以复制
            showCopyAndPasteMenuItem();
        }

        @Override
        public void menuDeselected(MenuEvent e) {
        }

        @Override
        public void menuCanceled(MenuEvent e) {
        }
    }

    /* *
     * @Description: 显示菜单项
     * @param []
     * @return void
     * @version v1.0
     * @author xiaoyan_lu
     * @date 2023/12/4 17:11
     */
    private void showCopyAndPasteMenuItem() {
        String selectedText = jTextArea.getSelectedText();
        if(selectedText != null && !selectedText.equals("")){
            jMenuItemCopy.setEnabled(true);
            jMenuItemShear.setEnabled(true);
        }else {
            jMenuItemCopy.setEnabled(false);
            jMenuItemShear.setEnabled(false);
        }
    }
}
